#include <unistd.h>
#include <types.h>
#include <stddef.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <sys/syscall.h>

int open(const char *path, int flags, ...)
{
    char abs[MAX_PATH_LEN+1];
    const char *p = NULL;
    int ret;

    if (!path)
        return -1;

    // build abspath
    memset(abs, 0, MAX_PATH_LEN);
    buildpath((char *)path, abs);

    p = abs;
    ret = syscall2(int, SYS_OPEN, (uintptr_t)p, flags);
    if (ret < 0)
    {
        _set_errno(-ret);
        ret = -1;
    }
    return ret;
}

int close(int fd)
{
    if (fd < 0)
        return -1;
    return syscall1(int, SYS_CLOSE, fd);
}

int read(int fd, void *buff, size_t bytes)
{
    if (fd < 0)
        return -1;
    return syscall3(int, SYS_READ, fd, (uintptr_t)buff, (uint32_t)bytes);
}

int write(int fd, void *buff, size_t bytes)
{
    if (fd < 0)
        return -1;
    return syscall3(int, SYS_WRITE, fd, (uintptr_t)buff, (uint32_t)bytes);
}

int ioctl(int fd, int cmd, void *arg)
{
    if (fd < 0)
        return -1;
    return syscall3(int, SYS_IOCTL, fd, cmd, (uintptr_t)arg);
}

int fcntl(int fd, int cmd, ...)
{
    va_list args;
    int64_t arg;

    va_start(args, cmd);
    if (fd < 0)
        return -1;
    arg = va_arg(args, uint64_t);
    va_end(args);
    return syscall3(int, SYS_FCNTL, fd, cmd, arg);
}

int lseek(int fd, offset_t off, int whence)
{
    if (fd < 0)
        return -1;
    return syscall3(int, SYS_LSEEK, fd, off, whence);
}

int access(const char *path, mode_t mode)
{
    char abs[MAX_PATH_LEN+1];
    char *p = abs;
    if (!path)
        return -1;
    buildpath((char *)path, abs);
    return syscall2(int, SYS_ACCESS, (uintptr_t)p, mode);
}

int unlink(const char *path)
{
    char abs[MAX_PATH_LEN+1];
    char *p = abs;
    if (!path)
        return -1;
    buildpath((char *)path, abs);
    return syscall1(int, SYS_UNLINK, (uintptr_t)p);
}

int ftruncate(int fd, offset_t off)
{
    if (fd < 0)
        return -1;
    return syscall2(int, SYS_FTRUNCATE, fd, off);
}

int fsync(int fd, int mode)
{
    if (fd < 0)
        return -1;
    return syscall2(int, SYS_FSYNC, fd, mode);
}

int fchmode(int fd, mode_t mode)
{
    if (fd < 0)
        return -1;
    return syscall2(int, SYS_FCHMOD, fd, mode);
}

int64_t tell(int fd)
{
    if (fd < 0)
        return -1;
    return syscall1(int, SYS_TELL, fd);
}

int fstat(int fd, status_t *buff)
{
    if (fd < 0)
        return -1;
    return syscall2(int, SYS_FSTATUS, fd, (uintptr_t)buff);
}

int dup(int fd)
{
    if (fd < 0)
        return -1;
    return syscall1(int, SYS_DUP, fd);
}

int dup2(int oldfd, int newfd)
{
    if (oldfd < 0 || newfd < 0)
        return -1;
    return syscall2(int, SYS_DUP2, oldfd, newfd);
}

int pipe(int fd[2])
{
    return syscall1(int, SYS_PIPE, (uintptr_t)fd);
}

int probedev(const char *name, char *buff, size_t len)
{
    return syscall3(int, SYS_PROBEDEV, (uintptr_t)name, (uintptr_t)buff, len);
}

int mkfifo(const char *name, mode_t mode)
{
    return syscall2(int, SYS_MKFIFO, (uintptr_t)name, mode);
}

